package com.moxi.mogublog.redis.service;

import com.moxi.mogublog.redis.vo.RedisInfoVO;
import redis.clients.jedis.Tuple;

import java.util.*;

/**
 * Jedis 工具接口 [Jedis是Redis官方推荐的Java连接开发工具]
 *
 * @author JackLi
 * @version 1.0.0
 * @date 2020/5/31 7:39
 */
public interface IRedisService {

    /**
     * 获取 redis 的详细信息
     *
     * @return
     */
    public List<RedisInfoVO> getRedisInfo();

    /**
     * eval-使用 Lua 解释器执行脚本
     *
     * @param script 一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数
     * @param keys
     * @param args
     * @param <T>
     * @return
     */
    public <T> Object eval(String script, List<String> keys, List<String> args);


    /** ------------------- 主要命令 [start]--------------------- */

    /**
     * ping-检测redis服务器是否能ping通
     *
     * @param <T>
     * @return
     */
    public <T> String ping();

    /**
     * getKeysSize-获取 redis key 数量
     *
     * @return
     */
    public Map<String, Object> getKeysSize();

    /**
     * getMemoryInfo-获取 redis 内存信息
     *
     * @return
     */
    public Map<String, Object> getMemoryInfo();

    /**
     * getKeys-获取指定的 key
     *
     * @param pattern 正则表达式
     * @return
     */
    public Set<String> getKeys(String pattern);

    /**
     * flushDB-删除db下的所有数据
     *
     * @param <T>
     * @return
     */
    public <T> String flushDB();

    /**
     * flushAll-通杀全部库
     *
     * @param <T>
     * @return
     */
    public <T> String flushAll();

    /**
     * pttl- 以毫秒为单位返回 (key) 的剩余过期时间
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> Long pttl(String key);


    /**
     * expire-设置 (key) 的过期时间，(key) 过期后将不再可用。单位以秒计
     *
     * @param key
     * @param seconds
     * @param <T>
     * @return
     */
    public <T> Long expire(String key, Integer seconds);

    /**
     * pExpire-设置 (key) 的过期时间，(key) 过期后将不再可用。单位以毫秒计
     *
     * @param key
     * @param milliSeconds 以毫秒为单位
     * @param <T>
     * @return
     */
    public <T> Long pExpire(String key, Long milliSeconds);

    /** ------------------- 主要命令 [end]--------------------- */


    /** -------------------key相关操作--------------------- */

    /**
     * 删除key
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> boolean delete(String key);

    /**
     * 批量删除key
     *
     * @param keys 多个键
     * @param <T>
     * @return
     */
    public <T> Long delete(Collection<String> keys);

    /**
     * 序列化key
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> byte[] dump(String key);

    /**
     * 是否存在key
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> Boolean exists(String key);

    /**
     * 设置过期时间
     *
     * @param key           键
     * @param timeoutSecond 过期时长，单位：秒
     * @param <T>
     * @return
     */
    public <T> Long expire(String key, long timeoutSecond);

    /**
     * 设置过期时间 [以 UNIX 时间戳(unix timestamp)格式]
     *
     * @param key  键
     * @param date 到期时间
     * @param <T>
     * @return
     */
    public <T> Long expireAt(String key, Date date);

    /**
     * 查找匹配的key
     *
     * @param pattern 键的匹配模式
     * @param <T>
     * @return
     */
    public <T> Set<String> keys(String pattern);

    /**
     * 将当前数据库的 key 移动到给定的数据库 db 当中
     *
     * @param key     键
     * @param dbIndex 库的序号
     * @param <T>
     * @return
     */
    public <T> Long move(String key, int dbIndex);

    /**
     * 移除 key 的过期时间，key 将持久保持
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> Long persist(String key);

    /**
     * 返回 key 的剩余的过期时间，单位：秒
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> Long getExpire(String key);

    /**
     * 从当前数据库中随机返回一个 key
     *
     * @param <T>
     * @return
     */
    public <T> String randomKey();

    /**
     * 修改 key 的名称
     *
     * @param oldKey 旧键
     * @param newKey 新键
     * @param <T>
     * @return
     */
    public <T> String rename(String oldKey, String newKey);

    /**
     * 仅当 newKey 不存在时，将 oldKey 改名为 newKey
     *
     * @param oldKey 旧键
     * @param newKey 新键
     * @param <T>
     * @return
     */
    public <T> Long renameIfAbsent(String oldKey, String newKey);

    /**
     * 返回 key 所储存的值的类型
     *
     * @param key 键
     * @param <T>
     * @return
     */
    public <T> String type(String key);


    /**
     * ------------- Redis数据类型1:字符串（String）：单值单value [start]---------------------
     */

    /**
     * 设置指定 key 的值
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> String set(String key, T value);

    /**
     * 获取指定 key 的值
     *
     * @param key
     * @return 字符串
     */
    public String get(String key);

    /**
     * 返回 key 中字符串值的子字符
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String getRange(String key, long start, long end);

    /**
     * 将给定 key 的值设为 value ，并返回 key 的旧值(old value)
     *
     * @param key
     * @param value
     * @return
     */
    public String getAndSet(String key, String value);

    /**
     * 对 key 所储存的字符串值，获取指定偏移量上的位(bit)
     *
     * @param key
     * @param offset
     * @return
     */
    public Boolean getBit(String key, long offset);

    /**
     * 批量获取
     *
     * @param keys
     * @return
     */
    public List<String> multiGet(Collection<String> keys);

    /**
     * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value
     *
     * @param key    位置
     * @param offset
     * @param value  值,true为1, false为0
     * @return
     */
    public boolean setBit(String key, long offset, boolean value);

    /**
     * 将值 value 关联到 key ，并将 key 的过期时间设为 timeout
     * <p/>
     * 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     *
     * @param key
     * @param value
     * @param timeoutSeconds 过期时间，单位：秒
     * @param <T>
     * @return
     */
    public <T> String setEx(String key, T value, int timeoutSeconds);

    /**
     * 只有在 key 不存在时设置 key 的值
     *
     * @param key
     * @param value
     * @return 之前已经存在返回false, 不存在返回true
     */
    public Long setIfAbsent(String key, String value);

    /**
     * 用 value 参数覆写给定 key 所储存的字符串值，从偏移量 offset 开始
     *
     * @param key
     * @param value
     * @param offset 从指定位置开始覆写
     */
    public Long setRange(String key, String value, long offset);

    /**
     * 获取字符串的长度
     *
     * @param key
     * @return
     */
    public Long size(String key);

    /**
     * 增加(自增长), 负数则为自减
     *
     * @param key
     * @param increment
     * @param <T>
     * @return
     */
    public <T> Long incrBy(String key, long increment);

    /**
     * 追加到末尾
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> Long append(String key, String value);

    /** ----------- Redis数据类型1:字符串（String）：单值单value [end]------------------------- */

    /** ----------- Redis数据类型2:哈希（Hash）：KV模式不变，但V是一个键值对 [start]------------------------- */

    /**
     * 获取存储在哈希表中指定字段的值
     *
     * @param key
     * @param field
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T hGet(String key, String field, Class<T> clazz);

    /**
     * 获取所有给定字段的值
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> Map<String, String> hGetAll(String key);

    /**
     * 获取所有给定字段的值
     *
     * @param key
     * @param hashKey
     * @param value
     * @return
     */
    public Long hPut(String key, String hashKey, String value);

    /**
     * 仅当hashKey不存在时才设置
     *
     * @param key
     * @param hashKey
     * @param value
     * @return
     */
    public Long hPutIfAbsent(String key, String hashKey, String value);

    /**
     * 删除一个或多个哈希表字段
     *
     * @param key
     * @param fields
     * @return
     */
    public Long hDelete(String key, String... fields);

    /**
     * 查看哈希表 key 中，指定的字段是否存在
     *
     * @param key
     * @param field
     * @return
     */
    public Boolean hExists(String key, String field);

    /**
     * 为哈希表 key 中的指定字段的整数值加上增量 increment
     *
     * @param key
     * @param field
     * @param increment
     * @return
     */
    public Long hIncrBy(String key, String field, long increment);

    /**
     * 为哈希表 key 中的指定字段的整数值加上增量 increment
     *
     * @param key
     * @param field
     * @param delta
     * @return
     */
    public Double hIncrByFloat(String key, String field, double delta);

    /**
     * 获取所有哈希表中的字段
     *
     * @param key
     * @return
     */
    public Set<String> hKeys(String key);

    /**
     * 获取哈希表中字段的数量
     *
     * @param key
     * @return
     */
    public Long hSize(String key);

    /**
     * 获取哈希表中所有值
     *
     * @param key
     * @return
     */
    public List<String> hValues(String key);

    /** ----------- Redis数据类型2:哈希（Hash）：KV模式不变，但V是一个键值对 [end]---------------------------- */


    /** ----------- Redis数据类型3:列表（List）：单值多value [start]---------------------------- */

    /**
     * 通过索引获取列表中的元素
     *
     * @param key
     * @param index
     * @return
     */
    public String lIndex(String key, long index);

    /**
     * 获取列表指定范围内的元素
     *
     * @param key
     * @param start 开始位置, 0是开始位置
     * @param end   结束位置, -1返回所有
     * @return
     */
    public List<String> lRange(String key, long start, long end);

    /**
     * 存储在list头部
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Long lLeftPush(String key, T value);

    /**
     * lLeftPushAll-将多个值 value 插入到列表 (key) 的表头,即从list左侧插入
     *
     * @param key
     * @param value
     * @return
     */
    public Long lLeftPushAll(String key, String... value);


    /**
     * 将多个值 value 插入到列表 (key) 的表头,即从list左侧插入
     *
     * @param key
     * @param values
     * @param <T>
     * @return
     */
    public <T> Long lLeftPushAll(String key, Collection<T> values);

    /**
     * 当list存在的时候才加入
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Long lLeftPushIfPresent(String key, T value);

    /**
     * 如果pivot存在,再pivot前面添加
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public Long lLeftPush(String key, String pivot, String value);

    /**
     * 将一个值 value 插入到列表 (key) 的表尾,即从list右侧插入
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Long lRightPush(String key, T value);

    /**
     * 将多个值 value 插入到列表 (key) 的表尾,即从list右侧插入
     *
     * @param key
     * @param value
     * @return
     */
    public Long lRightPushAll(String key, String... value);

    /**
     * 将多个值 value 插入到列表 (key) 的表尾,即从list右侧插入
     *
     * @param key
     * @param value
     * @return
     */
    public Long lRightPushAll(String key, Collection<String> value);

    /**
     * 为已存在的列表添加值
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Long lRightPushIfPresent(String key, T value);

    /**
     * 在pivot元素的右边添加值
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public Long lRightPush(String key, String pivot, String value);

    /**
     * 通过索引设置列表元素的值
     *
     * @param key
     * @param index 位置
     * @param value
     * @param <T>
     * @return
     */
    public <T> String lSet(String key, long index, T value);

    /**
     * 移出并获取列表的第一个元素
     *
     * @param key
     * @return 删除的元素
     */
    public String lLeftPop(String key);

    /**
     * 移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     *
     * @param key
     * @param timeoutSeconds 等待时间，单位：秒
     * @return
     */
    public String lBLeftPop(String key, long timeoutSeconds);

    /**
     * 移除并获取列表最后一个元素
     *
     * @param key
     * @return 删除的元素
     */
    public String lRightPop(String key);

    /**
     * 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     *
     * @param key
     * @param timeoutSeconds 等待时间，单位：秒
     * @return
     */
    public String lBRightPop(String key, long timeoutSeconds);

    /**
     * 移除列表的最后一个元素，并将该元素添加到另一个列表并返回
     *
     * @param sourceKey
     * @param destinationKey
     * @return
     */
    public String lRightPopAndLeftPush(String sourceKey, String destinationKey);

    /**
     * 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     *
     * @param sourceKey
     * @param destinationKey
     * @param timeoutSeconds 超时时间，单位：秒
     * @return
     */
    public String lBRightPopAndLeftPush(String sourceKey, String destinationKey, long timeoutSeconds);

    /**
     * 删除集合中值等于value得元素
     *
     * @param key
     * @param index index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素;
     *              index<0, 从尾部开始删除第一个值等于value的元素;
     * @param value
     * @return
     */
    public Long lRemove(String key, long index, String value);

    /**
     * 裁剪list
     *
     * @param key
     * @param start
     * @param end
     */
    public String lTrim(String key, long start, long end);

    /**
     * 获取列表长度
     *
     * @param key
     * @return
     */
    public Long lLen(String key);

    /** ----------- Redis数据类型3:列表（List）：单值多value [end] -------------------------- */


    /** ----------- Redis数据类型4:集合（Set）：单值多value [start] -------------------------- */

    /**
     * set 添加元素
     *
     * @param key
     * @param values
     * @return
     */
    public <T> Long sAdd(String key, String... values);

    /**
     * set移除元素
     *
     * @param key
     * @param values
     * @return
     */
    public Long sRemove(String key, String... values);

    /**
     * 移除并返回集合的一个随机元素
     *
     * @param key
     * @return
     */
    public String sPop(String key);

    /**
     * 将元素value从一个集合移到另一个集合
     *
     * @param key
     * @param value
     * @param destKey
     * @return
     */
    public Long sMove(String key, String value, String destKey);

    /**
     * 获取集合的大小
     *
     * @param key
     * @return
     */
    public Long sSize(String key);

    /**
     * 判断集合是否包含value
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean sIsMember(String key, String value);

    /**
     * 获取两个集合的交集
     *
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sIntersect(String key, String otherKey);

    /**
     * 获取key集合与多个集合的交集
     *
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sIntersect(String key, Collection<String> otherKeys);

    /**
     * key集合与otherKey集合的交集存储到destKey集合中
     *
     * @param key
     * @param otherKey
     * @param destKey
     * @return
     */
    public Long sIntersectAndStore(String key, String otherKey, String destKey);

    /**
     * 获取两个集合的并集
     *
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sUnion(String key, String otherKeys);

    /**
     * 获取两个集合的差集
     *
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sDifference(String key, String otherKey);

    /**
     * 获取集合所有元素
     *
     * @param key
     * @return
     */
    public Set<String> getSetMembers(String key);

    /**
     * 随机获取集合中的一个元素
     *
     * @param key
     * @return
     */
    public String sRandomMember(String key);

    /**
     * 随机获取集合中count个元素
     *
     * @param key
     * @param count
     * @return
     */
    public List<String> sRandomMembers(String key, int count);

    /**
     * 随机获取集合中count个元素并且去除重复的
     *
     * @param key
     * @param count
     * @return
     */
    public Set<String> sDistinctRandomMembers(String key, int count);


    /**---------- Redis数据类型4:集合（Set）：单值多value [end] --------------------------------*/


    /**---------- Redis数据类型5:有序集合zSet（sorted set） [start] --------------------------------*/

    /**
     * 添加元素,有序集合是按照元素的score值由小到大排列
     *
     * @param key
     * @param value
     * @param score
     * @return
     */
    public Long zAdd(String key, String value, double score);


    /**
     * 删除
     *
     * @param key
     * @param values
     * @return
     */
    public Long zRemove(String key, String... values);

    /**
     * 增加元素的score值，并返回增加后的值
     *
     * @param key
     * @param value
     * @param delta
     * @return
     */
    public Double zIncrementScore(String key, String value, double delta);

    /**
     * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
     *
     * @param key
     * @param value
     * @return 0表示第一位
     */
    public Long zRank(String key, String value);

    /**
     * 返回元素在集合的排名,按元素的score值由大到小排列
     *
     * @param key
     * @param value
     * @return
     */
    public Long zReverseRank(String key, String value);

    /**
     * 获取集合的元素, 从小到大排序
     *
     * @param key
     * @param start 开始位置
     * @param end   结束位置, -1查询所有
     * @return
     */
    public Set<String> zRange(String key, long start, long end);

    /**
     * 获取集合元素, 并且把score值也获取
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<Tuple> zRangeWithScores(String key, long start, long end);

    /**
     * 根据Score值查询集合元素
     *
     * @param key
     * @param min 最小值
     * @param max 最大值
     * @return
     */
    public Set<String> zRangeByScore(String key, double min, double max);

    /**
     * 根据Score值查询集合元素, 从小到大排序
     *
     * @param key
     * @param min 最小值
     * @param max 最大值
     * @return
     */
    public Set<Tuple> zRangeByScoreWithScores(String key, double min, double max);

    /**
     * @param key
     * @param min
     * @param max
     * @param start
     * @param end
     * @return
     */
    public Set<Tuple> zRangeByScoreWithScores(String key, double min, double max, int start, int end);

    /**
     * 获取集合的元素, 从大到小排序
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zReverseRange(String key, long start, long end);

    /**
     * 获取集合的元素, 从大到小排序, 并返回score值
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<Tuple> zReverseRangeWithScores(String key, long start, long end);

    /**
     * 根据Score值查询集合元素, 从大到小排序
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zReverseRangeByScore(String key, double min, double max);

    /**
     * 根据Score值查询集合元素, 从大到小排序
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<Tuple> zReverseRangeByScoreWithScores(String key, double min, double max);

    /**
     * @param key
     * @param min
     * @param max
     * @param start
     * @param end
     * @return
     */
    public Set<String> zReverseRangeByScore(String key, double min, double max, int start, int end);

    /**
     * 根据score值获取集合元素数量
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Long zCount(String key, double min, double max);

    /**
     * 获取集合大小
     *
     * @param key
     * @return
     */
    public Long zSize(String key);

    /**
     * 获取集合大小
     *
     * @param key
     * @return
     */
    public Long zZCard(String key);

    /**
     * 获取集合中value元素的score值
     *
     * @param key
     * @param value
     * @return
     */
    public Double zScore(String key, String value);

    /**
     * 移除指定索引位置的成员
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long zRemoveRange(String key, long start, long end);

    /**
     * 根据指定的score值的范围来移除成员
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Long zRemoveRangeByScore(String key, double min, double max);

}
